﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.ObjectModel;
using System.Windows.Media.Media3D;

using EQEmu.Database.Extensions;

namespace EQEmu.Spawns
{
    public class SpawnsCollectionChangedEventArgs : EventArgs
    {
        public IEnumerable<spawn2> AddedSpawns { get; set; }
        public IEnumerable<spawn2> RemovedSpawns { get; set; }
    }

    public class ZoneSpawns
    {
        private string _zoneShortName;
        private int _zoneVersion;
        private ObservableCollection<spawn2> _spawns = new ObservableCollection<spawn2>();
        private bool _hasModifications = false;

        public event EventHandler<SpawnsCollectionChangedEventArgs> SpawnsCollectionChanged;

        public ZoneSpawns(string zoneShortName,int zoneVersion=0)
        {
            _zoneShortName = zoneShortName;
            _zoneVersion = zoneVersion;
            _spawns.CollectionChanged += _spawns_CollectionChanged;
        }

        void _spawns_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs args)
        {
            var e = SpawnsCollectionChanged;
            if (e != null)
            {
                var arg = new SpawnsCollectionChangedEventArgs()
                {
                    AddedSpawns = args.NewItems != null ? args.NewItems.Cast<spawn2>() : null,
                    RemovedSpawns = args.OldItems != null ? args.OldItems.Cast<spawn2>() : null
                };
                e(this, arg);
            }
        }

        public int ZoneVersion
        {
            get { return _zoneVersion; }
        }

        public virtual bool HasModifications
        {
            get
            {
                return _hasModifications;
            }
        }

        public virtual spawn2 CreateSpawn()
        {
            var spawn = new spawn2();
            spawn.zone = ZoneShortName;
            spawn.version = ZoneVersion;
            //int id = 1;
            //if (_spawns.Count > 0)
            //{
            //    id = _spawns.Max(x => x.id) + 1;
            //}
            //spawn.id = id;
            return spawn;
        }

        public virtual void AddSpawn(spawn2 spawn)
        {
            _hasModifications = true;
            _spawns.Add(spawn);
        }

        public virtual void RemoveSpawn(spawn2 spawn)
        {
            _hasModifications = true;
            _spawns.Remove(spawn);
        }

        public spawn2 GetNearbySpawn(Point3D pt, double threshhold = 5.0)
        {
            double minDist = 9999.0;
            double dist = 9999.0;
            spawn2 candidate = null;

            foreach (spawn2 n in Spawns)
            {
                dist = Common.Functions.Distance(new Point3D(n.x, n.y, n.z), pt);
                if (dist < minDist)
                {
                    minDist = dist;
                    candidate = n;
                }
            }

            if (candidate != null && minDist < threshhold)
            {
                return candidate;
            }
            else
            {
                return null;
            }
        }

        public void SaveToFile(string path)
        {
            var spawns = Spawns.ToArray();
            spawns.ToXmlFile(path);
        }

        public static int GetVersionFromFileName(string file)
        {
            string filename = System.IO.Path.GetFileNameWithoutExtension(file);
            var split = filename.Split('.');
            if (split.Count() > 1)
            {
                return Int32.Parse(split.ElementAt(1));
            }
            else
            {
                return 0;
            }
        }

        public static ZoneSpawns LoadFromFile(string path)
        {
            ZoneSpawns zp = null;
            string zone = "";
            int version = GetVersionFromFileName(path);

            var spawns = (IEnumerable<spawn2>)(SerializationExtensions.FromXmlFile<spawn2[]>(path));
            if (spawns.Count() > 0)
            {
                zone = spawns.ElementAt(0).zone;
            }

            zp = new ZoneSpawns(zone, version);
            foreach (var sp in spawns)
            {
                zp.AddSpawn(sp);
            }
            zp._hasModifications = false;

            return zp;
        }

        public IEnumerable<spawn2> Spawns
        {
            get { return _spawns; }
        }

        public string ZoneShortName
        {
            get { return _zoneShortName; }
            private set
            {
                _zoneShortName = value;
            }
        }
    }
}
